# -*- coding: utf-8 -*- 
#########################################################################
## This is a samples controller
## - index is the default action of any application
## - user is required for authentication and authorization
## - download is for downloading files uploaded in the db (does streaming)
## - call exposes all registered services (none by default)
#########################################################################  
import math
import os

def index():
    if not auth.is_logged_in():
        redirect(URL('about'))
        
    return dict(message = T('Welcome to a Distributed Todo List'),
                user = auth.user_id)


@auth.requires_login()
def projects():
    return dict()


@auth.requires_login()
def addproject():
    form = SQLFORM(db.projects)

    if form.accepts(request.vars, session):
        db.users.insert(name = auth.user_id, project = form.vars.id)
        redirect(URL('projects'))

    return dict(form = form)


@auth.requires_login()
def projectinfo():
    members = []
    all_users = []
    users = []
    isNotMember = True

    record = request.args(0)
    records = db((db.users.project == record) &
                 (db.auth_user.id == db.users.name)).select(db.auth_user.id,
                  db.auth_user.username)

    for row in records:
        members.append((row.id, row.username))

        if auth.user_id == row.id:
            isNotMember = False

    records = db().select(db.auth_user.id, db.auth_user.username)

    for row in records:
        all_users.append((row.id, row.username))

    users = [x for x in all_users if x not in members]
    creator = db(db.projects.id == record).select(
                 db.projects.created_by)[0].created_by
    
    return dict(record = record, members = sorted(members),
                isNotMember = isNotMember, users = sorted(users),
                creator = creator)


@auth.requires_login()
def editproject():

    outstanding = db((db.todos.project==request.args(0))&
                     (db.todos.status!='Completed')).count()
    if outstanding != 0:
        crud.settings.update_deletable = False
    form = crud.update(db.projects, request.args(0), next = URL('projects'))
    
    return dict(form = form,
                outstanding = outstanding )


@service.json
def getMembers():
    rows = []
    project = request.args[2]
    page = int(request.vars.page)
    pagesize = int(request.vars.rows)
    limitby = (page * pagesize - pagesize, page * pagesize)

    records = db((db.users.project == project) &
                 (db.auth_user.id == db.users.name)).select(
                  db.auth_user.username, db.auth_user.email,
                  orderby = db.auth_user.username, limitby = limitby)

    for record in records:
        vals = []
        vals = [record.username, record.email]
        rows.append(dict(cell = vals))

    num_records = len(records)
    pages = math.ceil(num_records / float(pagesize))

    if not num_records:
        page = 0

    return dict(records = num_records, total = pages, page = page, rows = rows)


def updateMembers():
    current_members = []
    add_members = []
    remove_members = []
    request_members = []

    if type(request.vars['members[]']) is not list:
        request_members.append(request.vars['members[]'])
    else:
        request_members = request.vars['members[]']

    records = db((db.users.project == request.vars.record) &
                 (db.auth_user.id == db.users.name)).select(db.auth_user.id)

    for row in records:
        current_members.append(str(row.id))

    add_members = [x for x in request_members if x not in current_members]
    remove_members = [x for x in current_members if x not in request_members]

    for member in add_members:
        db.users.insert(name = int(member), project = request.vars.record)

    for member in remove_members:
        creator = db(db.projects.id == request.vars.record).select(
                     db.projects.created_by)[0].created_by

        if creator != int(member):
            db((db.users.name == int(member)) &
               (db.users.project == request.vars.record)).delete()

    return dict()


@service.json
def getProjects():
    rows = []
    user = request.args[2]
    page = int(request.vars.page)
    pagesize = int(request.vars.rows)
    orderby = db.projects[request.vars.sidx]

    if request.vars.sord == 'desc':
        orderby = ~orderby

    limitby = (page * pagesize - pagesize, page * pagesize)

    if user == 'all':
        fields = ['name', 'short_description','outstanding_todos','total_todos']
        results = db().select(db.projects.ALL, limitby = limitby,
                              orderby = orderby)
        for r in results:
            vals = []
            for f in fields:                
                if f == 'outstanding_todos':
                  vals.append(db((db.todos.project==r['id'])&
                                 (db.todos.status!='Completed')).count())
                elif f == 'total_todos':
                  vals.append(db(db.todos.project==r['id']).count())
                else:
                    rep = db.projects[f].represent
                    if rep:
                        vals.append(rep(r[f]))
                    else:
                        vals.append(r[f])
   
            rows.append(dict(id = r.id, cell = vals))
    else:
        results = db((db.users.name == user) &
                     (db.projects.id == db.users.project)).select(
                      db.projects.id, db.projects.name, limitby = limitby,
                      orderby = orderby)

        for r in results:
            vals = []
            vals = ["".join(['<b>', r.name, '</b>'])]
            rows.append(dict(id = r.id, cell = vals))

    records = len(results)
    pages = math.ceil(records / float(pagesize))

    if not records:
        page = 0

    return dict(records = records, total = pages, page = page, rows = rows)


@service.json
def getProjectInfo():

    rows = []
    fields = ['name', 'short_description', 'description', 'creation_date']
    project = request.args[2]

    record = db.projects(project)
    vals = []
    for f in fields:
        rep = db.projects[f].represent

        if rep:
            vals.append(str(rep(record[f])))
        else:
            vals.append(record[f])
    rows.append(dict(id = record.id, cell = vals))

    return dict(rows = rows)


@auth.requires_login()
def todos():                      
    results=db(db.todos.project==db.projects.id).select(db.projects.id,
                                                        db.projects.name,
                                                        distinct=True) 

    return dict(results=results)


@service.json
def getTodoInfo():
    rows = []
    project = request.args[2]
    page = int(request.vars.page)
    pagesize = int(request.vars.rows)
    orderby = db.todos[request.vars.sidx]

    if request.vars.sord == 'desc':
        orderby = ~orderby

    limitby = (page * pagesize - pagesize, page * pagesize)

    if 'all' in project:
        ignore, project = project.split('-')

        results = db(db.todos.project == project).select(db.todos.ALL,
                      limitby = limitby, orderby = orderby)

        fields = ['title', 'description', 'completion_date', 'status',
                  'assignee','comments']
    else:
        results = db((db.todos.assignee == auth.user_id) &
                     (db.todos.project == project)).select(db.todos.ALL,
                      limitby = limitby, orderby = orderby)

        fields = ['title', 'description', 'completion_date', 'status','comments']

    for r in results:
        vals = []
        for f in fields:
            if f=='comments':
                vals.append(db(db.todofeedback.todo==r['id']).count())
            else:
                rep = db.todos[f].represent
    
                if rep:
                    vals.append(str(rep(r[f])))
                else:
                    vals.append(r[f])
    
        rows.append(dict(id = r.id, cell = vals))
    
    records = len(results)
    pages = math.ceil(records / float(pagesize))

    if not records:
        page = 0

    return dict(records = records, total = pages, page = page, rows = rows)


@auth.requires_login()
def edittodos():
    record = db.todos(request.args(0))
    subset = db((db.users.project==record.project)&
                (db.auth_user.id==db.users.name) )

    member = db((db.users.project == record.project) &
                (auth.user_id == db.users.name)).select(db.users.name)

    if not member:
        redirect(URL(r = request, f = 'infopage',
                 vars = dict(target = request.env['http_referer'],
                 message = 'You are not a member of this project.')))

    db.todos.assignee.requires=IS_IN_DB(subset,'auth_user.id',db.auth_user._format)
    db.todos.project.readable=True
    db.todos.project.writable=False
    
    record.modified_by = auth.user_id
    form = crud.update(db.todos, record, next = URL('todos'))

    return dict(form = form)


@auth.requires_login()
def deleteComment():
    if len(request.args) > 0:
        comment_id=request.args(0)

    if 1 == db(db.todofeedback.id == comment_id).delete():
        response.flash = 'record deleted'

    redirect(request.env["http_referer"])

    return dict()

def deleteSiteFeedback():
    if len(request.args) > 0:
        comment_id=request.args(0)

    if 1 == db(db.sitefeedback.id == comment_id).delete():
        response.flash = 'record deleted'

    redirect(request.env["http_referer"])

    return dict()

@auth.requires_login()
def addtodos():
    if len(request.args) > 0:
       proj_id=request.args(0)
    else:
       response.flash = 'missing project id'
       redirect(URL('index'))
    
    member = db((db.users.project == proj_id) &
                (auth.user_id == db.users.name)).select(db.users.name)

    if not member:
        redirect(URL(r = request, f = 'infopage',
                 vars = dict(target = request.env['http_referer'],
                 message = 'You are not a member of this project.')))

    db.todos.project.default=proj_id
    db.todos.project.readable=True
    db.todos.project.writable=False
    
    subset = db((db.users.project==proj_id)&
                (db.auth_user.id==db.users.name) )

    db.todos.assignee.requires=IS_IN_DB(subset,'auth_user.id',db.auth_user._format)
    
    form = SQLFORM(db.todos)

    if form.accepts(request.vars, session):
        response.flash = 'form accepted'
        redirect(URL('index'))
    elif form.errors:
        response.flash = 'form has errors'

    return dict(form = form)


@auth.requires_login()
def commenttodos():
    page_size=5
    start_id=0
    
    if len(request.args) >= 2:
       start_id=request.args(1)

    if len(request.args) >= 1:
       todo_id=request.args(0)
    
    db.todofeedback.todo.writable=False
    db.todofeedback.todo.readable=False
    db.todofeedback.todo.default=todo_id

    form=crud.create(db.todofeedback)
    
    record = db.todos(todo_id)
    total_post = db(db.todofeedback.todo==todo_id).count()
    total_post = total_post-int(start_id)
    
    posts  = db(db.todofeedback.todo == todo_id).select(limitby=(int(start_id),
                                                                 int(start_id)+page_size),
                                       orderby = ~db.todofeedback.time_posted2)
    
    return dict(record = record, 
                posts = posts,
                form = form,
                total_post = total_post,
                page_size = page_size)

@auth.requires_login()
def comment():
    db.todofeedback.todo.writable=False
    db.todofeedback.todo.readable=False
    db.todofeedback.todo.default=request.args(0)

    form=SQLFORM(db.todofeedback,next=URL(args=request.args))

    if form.accepts(request.vars,session,formname=request.args(0)): 
        #redirect(request.env["http_referer"])
        pass

    comments=db(db.todofeedback.comment==request.args(0)).select()

    return dict(form=form,comments=comments)


def site_feedback():
    form=crud.create(db.sitefeedback)
    
    comments = db(db.sitefeedback.id>0).select(limitby = (0, 15),
                                               orderby = ~db.sitefeedback.id)

    return dict(form=form, comments=comments)


def about():
    return dict()


def infopage():
    message = request.vars.message
    target = request.vars.target

    return dict(message = H1(message), target = target)


def testComment():    
    if len(request.args) > 0:
       todo_id=request.args(0)

    record = db.todos(todo_id)
    posts  = db(db.todofeedback.todo == todo_id).select(limitby=(0,25),
                                             orderby=~db.todofeedback.time_posted2)

    return dict(record=record,
                posts=posts)


def user():
    """
    exposes:
    http://..../[app]/default/user/login 
    http://..../[app]/default/user/logout
    http://..../[app]/default/user/register
    http://..../[app]/default/user/profile
    http://..../[app]/default/user/retrieve_password
    http://..../[app]/default/user/change_password
    use @auth.requires_login()
        @auth.requires_membership('group name')
        @auth.requires_permission('read','table name',record_id)
    to decorate functions that need access control
    """
    return dict(form=auth())


def download():
    """
    allows downloading of uploaded files
    http://..../[app]/default/download/[filename]
    """
    return response.download(request,db)


def call():
    """
    exposes services. for example:
    http://..../[app]/default/call/jsonrpc
    decorate with @services.jsonrpc the functions to expose
    supports xml, json, xmlrpc, jsonrpc, amfrpc, rss, csv
    """
    session.forget()
    return service()
